﻿#region License, Terms and Conditions
//
// Copyright (c) 2008, aspZone.com
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY aspZone.com ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author(s):
//  John Rudolf Lewis (http://aspZone.com)
//
#endregion
namespace AspZone.Commerce.Repositories
{
    using System.Linq;
    using Model = AspZone.Commerce.Model;

    public class ProductRepository : IProductRepository
    {
        public bool IncludeCategories { get; set; }

        public IQueryable<Model.Product> Products
        {
            get
            {
                var dataContext = this.CreateDataContext();
                var query = from p in dataContext.Products
                            select new Model.Product
                            {
                                Id = p.ProductId,
                                DiscountPercent = p.DiscountPercent,
                                HandlingCharge = p.HandlingCharge,
                                LongDescription = p.LongDescription,
                                Name = p.Name,
                                Price = p.Price,
                                QuantityAvailable = p.QuantityAvailable,
                                SEOKeywords = p.SEOKeywords,
                                SEOName = p.SEOName,
                                SEOTitle = p.SEOTitle,
                                ShortDescription = p.ShortDescription,
                                Weight = p.Weight,
                                Images = (from i in p.ProductImages
                                          select new Model.Image
                                          {
                                              FullsizePath = i.FullsizePath,
                                              ThumbnailPath = i.ThumbnailPath
                                          }).ToList(),
                                Properties = (from prop in p.ProductProperties
                                              select new Model.ProductProperty
                                              {
                                                  Name = prop.Name,
                                                  Value = prop.Value
                                              }).ToList(),
                                Categories = (from pc in p.ProductCategories
                                              where this.IncludeCategories
                                              select new Model.Category
                                              {
                                                  Id = pc.Category.CategoryId,
                                                  Visible = pc.Category.Visible,
                                                  Image = new Model.Image { FullsizePath = pc.Category.ImageFullsizePath, ThumbnailPath = pc.Category.ImageThumbnailPath },
                                                  LongDescription = pc.Category.LongDescription,
                                                  Name = pc.Category.Name,
                                                  SEOKeywords = pc.Category.SEOKeywords,
                                                  SEOName = pc.Category.SEOName,
                                                  SEOTitle = pc.Category.SEOTitle,
                                                  ShortDescription = pc.Category.ShortDescription,
                                                  SortOrder = pc.Category.SortOrder
                                              }).ToList()
                            };
                return query;
            }
        }

        public void Save(Model.Product product)
        {
            using (var dataContext = this.CreateDataContext())
            {
                var dbProduct = new Database.Product
                {
                    ProductId = product.Id,
                    DiscountPercent = product.DiscountPercent,
                    HandlingCharge = product.HandlingCharge,
                    LongDescription = product.LongDescription,
                    Name = product.Name,
                    Price = product.Price,
                    QuantityAvailable = product.QuantityAvailable,
                    SEOKeywords = product.SEOKeywords,
                    SEOName = product.SEOName,
                    SEOTitle = product.SEOTitle,
                    ShortDescription = product.ShortDescription,
                    Weight = product.Weight
                };

                var images = from i in product.Images
                             select new Database.ProductImage
                             {
                                 FullsizePath = i.FullsizePath,
                                 ThumbnailPath = i.ThumbnailPath
                             };
                dbProduct.ProductImages.AddRange(images);

                if (this.IncludeCategories)
                {
                    var productCategories = from c in product.Categories
                                            select new Database.ProductCategory { CategoryId = c.Id };
                    dbProduct.ProductCategories.AddRange(productCategories);
                }

                var productProperties = from p in product.Properties
                                        select new Database.ProductProperty
                                        {
                                            Name = p.Name,
                                            Value = p.Value
                                        };
                dbProduct.ProductProperties.AddRange(productProperties);

                
                if (dbProduct.ProductId == 0)
                {
                    dataContext.Products.InsertOnSubmit(dbProduct);
                }
                else
                {
                    dataContext.Products.Attach(dbProduct, true);
                }

                dataContext.ProductImages.DeleteAllOnSubmit(dataContext.ProductImages.Where(pi => pi.ProductId == dbProduct.ProductId));
                dataContext.ProductImages.InsertAllOnSubmit(dbProduct.ProductImages);

                dataContext.ProductProperties.DeleteAllOnSubmit(dataContext.ProductProperties.Where(p => p.ProductId == dbProduct.ProductId));
                dataContext.ProductProperties.InsertAllOnSubmit(dbProduct.ProductProperties);

                if (this.IncludeCategories)
                {
                    dataContext.ProductCategories.DeleteAllOnSubmit(dataContext.ProductCategories.Where(pc => pc.ProductId == dbProduct.ProductId));
                    dataContext.ProductCategories.InsertAllOnSubmit(dbProduct.ProductCategories);
                }

                dataContext.SubmitChanges();

                product.Id = dbProduct.ProductId;
            }
        }

        public void Delete(Model.Product product)
        {
            using (var dataContext = this.CreateDataContext())
            {
                dataContext.ProductImages.DeleteAllOnSubmit(dataContext.ProductImages.Where(pi => pi.ProductId == product.Id));
                dataContext.ProductCategories.DeleteAllOnSubmit(dataContext.ProductCategories.Where(pc => pc.ProductId == product.Id));
                dataContext.Products.DeleteAllOnSubmit(dataContext.Products.Where(p => p.ProductId == product.Id));

                dataContext.SubmitChanges();
            }
        }

        private Database.CommerceDataContext CreateDataContext()
        {
            var ctx = new Database.CommerceDataContext();
            return ctx;
        }
    }
}
